package compiler;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import descriptors.AbstractDescr;

public class SymbolTable {
	
	private final Compiler compiler;
	private final Map<Integer, Map<String, AbstractDescr>> symbolTable=new HashMap<Integer, Map<String,AbstractDescr>>();
	
	public SymbolTable(Compiler compiler){
		this.compiler=compiler;
	}
	
	public AbstractDescr get(int level, String name){
		Map<String,AbstractDescr> firstResult=symbolTable.get(level);
		if(firstResult!=null) return firstResult.get(name);
		else return null;
	}
	
	public boolean levelContains(int level, String name){
		Map<String,AbstractDescr> levelMap=symbolTable.get(level);
		if(levelMap!=null){
			return levelMap.containsKey(name);
		}
		else return false;
	}
	
	public void resetLevel(int level){
		symbolTable.put(level,new HashMap<String,AbstractDescr>());
	}
	
	public void set(int level, String name,AbstractDescr descriptor){
		Map<String,AbstractDescr> map=symbolTable.get(level);
		if(map==null) symbolTable.put(level, new HashMap<String,AbstractDescr>());
		symbolTable.get(level).put(name, descriptor);
	}
	
	public void set(String name,AbstractDescr descriptor){
		set(compiler.level(),name,descriptor);
	}
	
	public AbstractDescr search(int level, String ident) {
		boolean stop = false;
		AbstractDescr descr = null;
		for (int i = level; (i >= 0 && !stop); i--){
			if(symbolTable.get(i)==null) symbolTable.put(i, new HashMap<String,AbstractDescr>());
			descr = symbolTable.get(i).get(ident);
			if (descr != null) stop = true;
		}
		return descr;
	}
	
	public void print() {
		for(Entry<Integer, Map<String, AbstractDescr>> levelEntry : symbolTable.entrySet()){
			System.out.println(levelEntry.getKey());
			for(Entry<String, AbstractDescr> entry : levelEntry.getValue().entrySet()) {
				System.out.print(entry.getKey() + ":\n");
				entry.getValue().print();
			}
		}
		
	}
	

}
